package top.canyue.eca_manager.service.impl;

import com.alibaba.fastjson2.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import top.canyue.eca_manager.bean.ConferenceDetail;
import top.canyue.eca_manager.bean.ReDetail;
import top.canyue.eca_manager.bean.Result;
import top.canyue.eca_manager.mapper.ConferenceDetailMapper;
import top.canyue.eca_manager.service.ConferenceDetailService;
import top.canyue.eca_manager.service.ConferenceService;
import top.canyue.eca_manager.service.LogService;
import top.canyue.eca_manager.service.RedisService;
import top.canyue.eca_manager.tool.ParamTools;

import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;

@Service
public class ConferenceDetailServiceImpl implements ConferenceDetailService {
    @Autowired
    RedisService redisService;

    @Autowired
    ConferenceDetailMapper conferenceDetailMapper;

    @Autowired
    ConferenceService conferenceService;

    @Autowired
    LogService logService;

    private static boolean isSupportedEmotion(String emotion) {
        return emotion.equals("sad")
                || emotion.equals("angry")
                || emotion.equals("surprise")
                || emotion.equals("fear")
                || emotion.equals("happy")
                || emotion.equals("disgust")
                || emotion.equals("neutral");
    }

    private static String getMD5(String input) {
        try {
            // 创建一个MessageDigest实例，并指定为MD5算法
            MessageDigest md = MessageDigest.getInstance("MD5");

            // 将输入字符串转换为字节数组，并更新摘要
            byte[] messageDigest = md.digest(input.getBytes(StandardCharsets.UTF_8));

            // 将字节数组转换为32个十六进制字符的字符串
            BigInteger number = new BigInteger(1, messageDigest);
            StringBuilder hashtext = new StringBuilder(number.toString(16));
            // 如果生成的哈希文本少于32个字符，则在前面填充0
            while (hashtext.length() < 32) {
                hashtext.insert(0, "0");
            }
            return hashtext.toString();
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }

    //map转Json 目前被fastjson替代
//    private String mapToJson(Map<String,Integer> map){
//        StringBuilder json = new StringBuilder();
//        json.append("{");
//        map.forEach((k,v)-> json.append("'").append(k).append("':").append(v).append(","));
//        json.delete(json.length()-1,json.length());
//        json.append("}");
//        return json.toString();
//    }

    @Override
    //更新会议缓存数据-累加计数情绪数据
    public Result incrCache(String conferenceId, String userId, String emotion) {
        Result result = new Result();
        if (!isSupportedEmotion(emotion)) {
            result.setStatus(500);
            result.setMsg("接收到不支持的情绪,本条数据不影响缓存");
            return result;
        }

        if (Objects.equals(conferenceId, "") || Objects.equals(userId, "") || Objects.equals(emotion, "")) {
            result.setStatus(500);
            result.setMsg("存在空参数");
            return result;
        }

        //Redis中Hash key 利用 eca:会议ID-用户ID 命名
        //KEY_PREFIX 已在RedisService中定义
        String key = String.format("%s-%s", conferenceId, userId);

        boolean flag = redisService.hIncrBy(key, emotion, 1);
        if (flag) {
            result.setStatus(200);
            result.setMsg("累加记录成功");
        } else {
            result.setStatus(500);
            result.setMsg("累加记录失败");
        }

        return result;
    }

    @Override
    public Result getCache(String conferenceId, String userId) {
        Result result = new Result();

        if (Objects.equals(conferenceId, "") || Objects.equals(userId, "")) {
            result.setStatus(500);
            result.setMsg("存在空参数");
            return result;
        }

        //Redis中Hash key 利用 eca:会议ID-用户ID 命名
        //KEY_PREFIX 已在RedisService中定义
        String key = String.format("%s-%s", conferenceId, userId);

        Set<String> items = redisService.hKeys(key);

        if (items == null || items.isEmpty()) {
            result.setStatus(500);
            result.setMsg("未找到记录,请检查会议ID和用户ID");
            return result;
        }

        Map<String, Integer> data = new HashMap<>();
        for (String item : items) {
            data.put(item, redisService.hGet(key, item));
        }

        result.setMsg("获取成功");
        result.setStatus(200);
        result.setData(JSON.toJSONString(data));

        return result;
    }

    @Override
    public Result persistentAllCacheByconferenceId(String conferenceId) {
        Result result = new Result();
        boolean isPersistent = conferenceService.getPersistentById(conferenceId);
        if (isPersistent) {
            result.setStatus(500);
            result.setMsg("持久化失败,该会议事先已经被持久化");
            return result;
        }
        try{
            List<String> userIds = conferenceDetailMapper.getUserIdByConferenceId(conferenceId);
            ArrayList<String> failUserIds = new ArrayList<>();
            userIds.forEach((String userId) -> {
                Result re = persistentCache(conferenceId,userId);
                if(re.getStatus() != 200){ failUserIds.add(userId); }
            });
            result.setStatus(200);
            if(!failUserIds.isEmpty()){
                result.setMsg("持久化操作成功，但有部分数据持久化失败");
                result.setData(failUserIds);
            }else{
                result.setMsg("持久化成功");
            }
            boolean flag_updatePersistent = conferenceService.updatePersistent(conferenceId, true);
            if (!flag_updatePersistent) {
                result.setStatus(500);
                result.setMsg("持久化操作成功,但在修改会状态时失败");
                result.setData(conferenceId);
                return result;
            }
        } catch (Exception e) {
//            System.out.println(e);
            result.setStatus(500);
            result.setMsg("持久化失败");
        }
        return result;
    }

    @Override
    public Result persistentCache(String conferenceId, String userId) {
        Result result = new Result();

        if (Objects.equals(conferenceId, "") || Objects.equals(userId, "")) {
            result.setStatus(500);
            result.setMsg("存在空参数");
            return result;
        }
        Result re = getCache(conferenceId, userId);
        Map<String, Integer> data = null;
        if(re.getStatus() == 200){
            data = JSON.parseObject(re.getData().toString(), Map.class);
        }
        if (data == null) {
            result.setStatus(500);
            result.setMsg("找不到缓存");
            return result;
        }
        try {
            boolean flag = conferenceDetailMapper.persistentCache(conferenceId, userId, data) == 1;
            if (flag) {
                result.setStatus(200);
                result.setMsg("缓存持久化成功");
            } else {
                result.setStatus(500);
                result.setMsg("缓存持久化失败");
            }
        } catch (DuplicateKeyException e) {
            result.setStatus(500);
            result.setMsg("缓存持久化失败,本数据可能已经被持久化");
        }
        logService.record(null,
                result.getStatus() == 200 ? "INFO" : "ERROR"
                , "persistentCache", ParamTools.paramsToJsonString(conferenceId, userId), result.getStatus());
        return result;
    }

    @Override
    public Result getDetailById(String id){
        Result result = new Result();
        if (Objects.equals(id, "")) {
            result.setStatus(500);
            result.setMsg("ID不能为空");
            return result;
        }

        ConferenceDetail conferenceDetail = conferenceDetailMapper.getDetailById(id);
        if(conferenceDetail != null){
            result.setStatus(200);
            result.setMsg("OK");
            result.setData(conferenceDetail);
        }else{
            result.setStatus(500);
            result.setMsg("未找到该数据");
        }

        return result;
    }

    @Override
    public Result joinConference(String conferenceId, List<String> userIdList) {
        Result result = new Result();
        if (userIdList.isEmpty()) {
            result.setStatus(500);
            result.setMsg("用户ID不得为空");
            return result;
        }
        if (conferenceId.isEmpty()) {
            result.setStatus(500);
            result.setMsg("会议ID不得为空");
            return result;
        }
        List<String> failUserIds = new ArrayList<>();
        userIdList.forEach((String userId) -> {
            Result re = joinConference(conferenceId, userId);
            if (re.getStatus() != 200) {
                failUserIds.add(userId);
            }
        });
        result.setStatus(200);
        if (failUserIds.isEmpty()) {
            result.setMsg("OK");
            return result;
        }
        result.setMsg("操作执行成功，但有部分用户加入失败，可能该用户已加入");
        result.setData(failUserIds);
        return result;
    }

    @Override
    public Result joinConference(String conferenceId, String userId){
        Result result = new Result();
        if(conferenceId.isEmpty() || userId.isEmpty()){
            result.setStatus(500);
            result.setMsg("会议ID或用户ID不得为空");
            return result;
        }
        String uuid = getMD5(conferenceId + "-" + userId);
        try{
            boolean flag = conferenceDetailMapper.joinConference(uuid, conferenceId, userId) == 1;
            if (flag) {
                result.setStatus(200);
                result.setMsg("加入会议成功");
                result.setData("'" + String.format(uuid) + "'");
            } else {
                result.setStatus(500);
                result.setMsg("加入会议失败");
            }
        }catch (Exception e){
            result.setStatus(500);
            result.setMsg("加入会议失败,可能该用户以加入会议，或是用户以及会议不存在");
        }
        logService.record(null,
                result.getStatus() == 200 ? "INFO" : "ERROR"
                , "joinConference", ParamTools.paramsToJsonString(conferenceId, userId), result.getStatus());
        return result;
    }

    @Override
    public Result leaveConferenceByAllUser(List<String> userIdList, String conferenceId) {
        Result result = new Result();
        if (conferenceId.isEmpty()) {
            result.setStatus(500);
            result.setMsg("会议ID不得为空");
        }
        if (userIdList.isEmpty()) {
            result.setStatus(500);
            result.setMsg("用户ID不得为空");
            return result;
        }
        int updateCollCount = conferenceDetailMapper.leaveConferenceByAllUser(userIdList, conferenceId);
        if (updateCollCount == 0) {
            result.setStatus(500);
            result.setMsg("移除操作失败");
            return result;
        }
        if (updateCollCount != userIdList.size()) {
            result.setStatus(500);
            result.setMsg("有部分用户移除失败");
            logService.record(null, "WARN", "leaveConferenceByAllUser",
                    ParamTools.paramsToJsonString(conferenceId, userIdList), result.getStatus());
            return result;
        }
        result.setStatus(200);
        result.setMsg("OK");
        logService.record(null, "INFO", "leaveConferenceByAllUser",
                ParamTools.paramsToJsonString(conferenceId, userIdList), result.getStatus());
        return result;
    }

    @Override
    public Result leaveConference(String userId, String conferenceId) {
        Result result = new Result();
        if (conferenceId.isEmpty()) {
            result.setStatus(500);
            result.setMsg("会议ID不得为空");
        }
        if (userId.isEmpty()) {
            result.setStatus(500);
            result.setMsg("用户ID不得为空");
            return result;
        }
        boolean flag = conferenceDetailMapper.leaveConference(userId, conferenceId) > 0;
        if (flag) {
            result.setStatus(200);
            result.setMsg("OK");
            logService.record(null, "WARN", "leaveConference",
                    ParamTools.paramsToJsonString(conferenceId, userId), result.getStatus());
            return result;
        }
        result.setStatus(500);
        result.setMsg("移除失败");
        logService.record(null, "INFO", "leaveConference",
                ParamTools.paramsToJsonString(conferenceId, userId), result.getStatus());
        return result;
    }

    @Override
    public Result getDetailByConferenceId(String conferenceId) {
        Result result = new Result();
        if (conferenceId.isEmpty()) {
            result.setStatus(500);
            result.setMsg("会议ID不得为空");
            return result;
        }
        List<ReDetail> details = conferenceDetailMapper.getDetailByConferenceId(conferenceId);
        if (!details.isEmpty()) {
            result.setStatus(200);
            result.setMsg("OK");
            result.setData(details);
        } else {
            result.setStatus(500);
            result.setMsg("找不到数据_也有可能是无人参与或会议不存在");
        }
        return result;
    }

    @Override
    public Result getUserIdByConferenceId(String conferenceId) {
        Result result = new Result();
        result.setStatus(200);
        result.setMsg("OK");
        result.setData(conferenceDetailMapper.getUserIdByConferenceId(conferenceId));
        return result;
    }

    @Override
    public Result getUserNameByConferenceId(String conferenceId) {
        Result result = new Result();
        result.setStatus(200);
        result.setMsg("OK");
        result.setData(conferenceDetailMapper.getUserNameByConferenceId(conferenceId));
        return result;
    }

}
